import axios, { AxiosInstance } from 'axios';
import { MonitoredTokenService } from '@/services/token/MonitoredTokenService';
import { createModuleLogger } from '@/utils/logger';

const logger = createModuleLogger('price-update-service');

export class PriceUpdateService {
  private static instance: PriceUpdateService;
  private monitoredTokenService: MonitoredTokenService;
  private httpClient: AxiosInstance;
  private updateInterval?: NodeJS.Timeout;
  private isUpdating = false;
  private readonly updateIntervalMs = 60 * 60 * 1000; // 1小时
  private readonly batchSize = 100; // 每次最多获取100个代币价格
  private readonly requestDelay = 2000; // CoinGecko API请求间隔2秒

  private constructor() {
    this.monitoredTokenService = MonitoredTokenService.getInstance();
    
    // 创建HTTP客户端
    this.httpClient = axios.create({
      baseURL: 'https://api.coingecko.com/api/v3',
      timeout: 30000,
      headers: {
        'User-Agent': 'ChainWatch/1.0'
      }
    });
  }

  public static getInstance(): PriceUpdateService {
    if (!PriceUpdateService.instance) {
      PriceUpdateService.instance = new PriceUpdateService();
    }
    return PriceUpdateService.instance;
  }

  // 启动定时价格更新
  public start(): void {
    if (this.updateInterval) {
      logger.info('价格更新服务已在运行中');
      return;
    }

    logger.info(`🚀 启动价格更新服务，更新间隔: ${this.updateIntervalMs / 1000 / 60} 分钟`);
    
    // 立即执行一次价格更新
    this.updatePrices().catch(error => {
      logger.error('初始价格更新失败:', error);
    });

    // 设置定时更新
    this.updateInterval = setInterval(async () => {
      try {
        await this.updatePrices();
      } catch (error) {
        logger.error('定时价格更新失败:', error);
      }
    }, this.updateIntervalMs);

    logger.info('✅ 价格更新服务已启动');
  }

  // 停止定时价格更新
  public stop(): void {
    if (this.updateInterval) {
      clearInterval(this.updateInterval);
      this.updateInterval = undefined;
      logger.info('🛑 价格更新服务已停止');
    }
  }

  // 手动触发价格更新
  public async updatePrices(): Promise<void> {
    if (this.isUpdating) {
      logger.info('价格更新正在进行中，跳过此次更新');
      return;
    }

    this.isUpdating = true;
    const startTime = Date.now();
    
    try {
      logger.info('🔄 开始更新代币价格...');
      
      // 获取需要更新的代币列表
      const tokensToUpdate = await this.monitoredTokenService.getTokensNeedingPriceUpdate(1); // 1小时内未更新的
      
      if (tokensToUpdate.length === 0) {
        logger.info('✅ 所有代币价格都是最新的');
        return;
      }

      logger.info(`📊 需要更新 ${tokensToUpdate.length} 个代币的价格`);
      
      let totalUpdated = 0;
      
      // 分批处理，避免API限制
      for (let i = 0; i < tokensToUpdate.length; i += this.batchSize) {
        const batch = tokensToUpdate.slice(i, i + this.batchSize);
        const batchNum = Math.floor(i / this.batchSize) + 1;
        const totalBatches = Math.ceil(tokensToUpdate.length / this.batchSize);
        
        logger.info(`📦 处理批次 ${batchNum}/${totalBatches} (${batch.length} 个代币)`);
        
        try {
          const updated = await this.updatePriceBatch(batch);
          totalUpdated += updated;
          
          // API请求间隔
          if (i + this.batchSize < tokensToUpdate.length) {
            logger.debug(`⏳ 等待 ${this.requestDelay}ms 后处理下一批...`);
            await new Promise(resolve => setTimeout(resolve, this.requestDelay));
          }
          
        } catch (error) {
          logger.error(`批次 ${batchNum} 更新失败:`, error);
        }
      }
      
      const duration = Date.now() - startTime;
      logger.info(`✅ 价格更新完成: ${totalUpdated}/${tokensToUpdate.length} 个代币，耗时 ${duration}ms`);
      
    } catch (error) {
      logger.error('价格更新失败:', error);
    } finally {
      this.isUpdating = false;
    }
  }

  // 批量更新代币价格
  private async updatePriceBatch(tokens: Array<{symbol: string, coingeckoId: string}>): Promise<number> {
    try {
      // 构建CoinGecko API请求
      const coinIds = tokens.map(t => t.coingeckoId).join(',');
      const response = await this.httpClient.get('/simple/price', {
        params: {
          ids: coinIds,
          vs_currencies: 'usd',
          include_market_cap: 'true',
          include_24hr_change: 'true',
          include_24hr_vol: 'true'
        }
      });

      if (response.status !== 200 || !response.data) {
        throw new Error(`API请求失败: ${response.status}`);
      }

      const priceData = response.data;
      const priceUpdates: Array<{symbol: string, price: number}> = [];

      // 处理每个代币的价格数据
      for (const token of tokens) {
        const data = priceData[token.coingeckoId];
        if (data && data.usd && data.usd > 0) {
          priceUpdates.push({
            symbol: token.symbol,
            price: data.usd
          });
        } else {
          logger.warn(`未获取到 ${token.symbol} (${token.coingeckoId}) 的有效价格数据`);
        }
      }

      // 批量更新数据库
      if (priceUpdates.length > 0) {
        const updated = await this.monitoredTokenService.updateTokenPrices(priceUpdates);
        logger.info(`📊 批次更新完成: ${updated}/${tokens.length} 个代币`);
        return updated;
      } else {
        logger.warn('批次中没有有效的价格数据');
        return 0;
      }

    } catch (error) {
      logger.error('批量价格更新失败:', error);
      return 0;
    }
  }

  // 获取服务状态
  public getStatus(): {
    isRunning: boolean;
    isUpdating: boolean;
    updateIntervalMinutes: number;
    nextUpdateTime?: Date;
  } {
    return {
      isRunning: !!this.updateInterval,
      isUpdating: this.isUpdating,
      updateIntervalMinutes: this.updateIntervalMs / 1000 / 60,
      nextUpdateTime: this.updateInterval ? new Date(Date.now() + this.updateIntervalMs) : undefined
    };
  }
} 